package cn.bzc.data.process.service.impl;

import cn.bzc.data.process.listener.PmBillDataListener;
import cn.bzc.data.process.model.dao.*;
import cn.bzc.data.process.model.entity.*;
import cn.bzc.data.process.service.PmBillDataService;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PmBillDataServiceImpl implements PmBillDataService {
    @Resource
    private PmBillDataDao pmBillDataDao;
    @Resource
    private PmBillDataTestDao pmBillDataTestDao;
    @Resource
    private PmBillDetailDao pmBillDetailDao;
    @Resource
    private PmBillDao pmBillDao;
    @Resource
    private OrderDao orderDao;

    private static final String SPLIT = ":";
    @Override
    @SneakyThrows
    public void initPmBillData() {
        /*ClassPathResource classPathResource = new ClassPathResource("test/");
        File parentFile = classPathResource.getFile();
        File[] files = parentFile.listFiles();
        assert files != null;
        for (File file : files) {
            String fileName = file.getName();
            log.info("读取文件：{} 开始",fileName);
            List<PmBillExcelData> dataList = loadFromExcel(file);
            log.info("读取文件：{} 结束",fileName);
        }

        log.info("你好");*/


    }
    @Transactional
    @Override
    public void replaceData() {
        List<PmBillExcelData> dataList = pmBillDataDao.list(new LambdaQueryWrapper<PmBillExcelData>().isNotNull(PmBillExcelData::getBillId));
        log.info("需要替换的数据：{} 总数",dataList.size());
        Set<String> stationNoList = dataList.stream().map(PmBillExcelData::getStationNo).collect(Collectors.toSet());
        List<OrdOrderInfo> orderList = orderDao.list(new LambdaQueryWrapper<OrdOrderInfo>().in(OrdOrderInfo::getStationno, stationNoList));
        Map<String, OrdOrderInfo> orderInfoMap = orderList.stream().collect(Collectors.toMap(OrdOrderInfo::getStationno, Function.identity(), (key1, key2) -> key1));
        Map<Integer, OrdOrderInfo> orderIdMap = orderList.stream().collect(Collectors.toMap(OrdOrderInfo::getOrderid, Function.identity(), (key1, key2) -> key1));
        Set<Integer> orderIdList = new HashSet<>();
        dataList.forEach(item->{
            Integer orderId = orderInfoMap.get(item.getStationNo()).getOrderid();
            item.setOrderId(orderId);
            orderIdList.add(orderId);
        });

        Map<String, PmBillExcelData> dataMap = dataList.stream().collect(Collectors.toMap(item -> item.getOrderId() + SPLIT + item.getBalanceNode(), Function.identity(), (key1, key2) -> key1));
        // 查询未存在账单数据的电站
        /*for (Integer orderId : orderIdList) {
            List<PmBill>  billList = pmBillDao.list(new LambdaQueryWrapper<PmBill>().eq(PmBill::getOrderid, orderId));
            if (CollectionUtils.isEmpty(billList)) {
                log.info("未查询到账单数据，电站id:{},电站编号：{}",orderId,orderIdMap.get(orderId).getStationno());
            }
        }*/
        List<PmBillExcelDataTest> finalDataList = new ArrayList<>();
        List<PmBill> errorPmBillList = new ArrayList<>();
        List<PmBill> pmBillList = pmBillDao.list(new LambdaQueryWrapper<PmBill>().in(PmBill::getOrderid, orderIdList));
        for (PmBill info : pmBillList) {
            if(info == null || info.getBillid() == null) {
                log.info("数据异常：{}", JSON.toJSONString(info));
            }
            assert info != null;
            PmBillExcelData pmBillExcelData = dataMap.get(info.getOrderid() + SPLIT + info.getSourcetype());
            if(pmBillExcelData !=null) {
                pmBillExcelData.setBillId(info.getBillid());
                pmBillExcelData.setId(null);
                PmBillExcelDataTest data = new PmBillExcelDataTest();
                BeanUtils.copyProperties(pmBillExcelData,data);
                if(info.getBillcost().compareTo(BigDecimal.ZERO) < 0) {
                    data.setTotalPower("-"+data.getTotalPower());
                    data.setPrice("-"+data.getPrice());
                }
                finalDataList.add(data);
            } else {
                errorPmBillList.add(info);
            }

        }
        for (PmBill pmBill : errorPmBillList) {
            log.info("账单：{},电站id：{},结算节点：{}",pmBill.getBillid(),pmBill.getOrderid(),pmBill.getSourcetype());
        }
        log.info("总共数据:{}",finalDataList.size());
        pmBillDataTestDao.saveBatch(finalDataList);
//        pmBillDataDao.updateBatchById(dataMap.values());

//        int i = 1/0;
    }


    @Override
    public void check() {
        List<PmBillExcelDataTest> sourceDataList = pmBillDataTestDao.list();
        Map<Integer, PmBillExcelDataTest> pmBillExcelDataTestMap = sourceDataList.stream().collect(Collectors.toMap(PmBillExcelDataTest::getBillId, Function.identity()));
        List<Integer> billIdList = sourceDataList.stream().map(PmBillExcelDataTest::getBillId).collect(Collectors.toList());
        List<PmBill> pmBillList = pmBillDao.list();
    }




    @Override
    @Transactional
    public void replaceDataV2() {
        List<PmBillExcelDataTest> dataList = pmBillDataTestDao.list();

        log.info("需要替换的数据：{} 总数",dataList.size());
        Map<Integer, PmBillExcelDataTest> dataMap = dataList.stream().filter(item->item.getBillId() != null)
                .collect(Collectors.toMap(PmBillExcelDataTest::getBillId,Function.identity(),(key1,key2)->key1));
        List<Integer> billIdList = dataMap.values().stream().map(PmBillExcelDataTest::getBillId).collect(Collectors.toList());
        List<PmBill> pmBillList = pmBillDao.list(new LambdaQueryWrapper<PmBill>().in(PmBill::getBillid, billIdList));
        List<PmBillDetail> pmBillDetailList = pmBillDetailDao.list(new LambdaQueryWrapper<PmBillDetail>().in(PmBillDetail::getBillid, billIdList));
        List<PmBill> errorList1 = new ArrayList<>();
        List<PmBillDetail> errorList2 = new ArrayList<>();
        List<PmBillDetail> errorList3 = new ArrayList<>();
        for (PmBill pmBill : pmBillList) {
            String priceStr = dataMap.get(pmBill.getBillid()).getPrice();
            BigDecimal cost = new BigDecimal(priceStr);
            if(cost.compareTo(pmBill.getBillcost()) != 0) {
                errorList1.add(pmBill);
            }
            pmBill.setBillcost(cost);
        }
        for (PmBillDetail pmBillDetail : pmBillDetailList) {
            PmBillExcelDataTest pmBillExcelData = dataMap.get(pmBillDetail.getBillid());
            String priceUnitStr = pmBillExcelData.getPriceUnit();
            String totalPowerStr = pmBillExcelData.getTotalPower();
            BigDecimal priceUnit = new BigDecimal(priceUnitStr);
            int totalPower = Integer.parseInt(totalPowerStr);
            if(totalPower != pmBillDetail.getTotalpower()) {
                errorList2.add(pmBillDetail);
            }
            if(priceUnit.compareTo(pmBillDetail.getPrice())!=0) {
                errorList3.add(pmBillDetail);
            }
            pmBillDetail.setPrice(priceUnit);
            pmBillDetail.setTotalpower(totalPower);
        }

//        pmBillDao.updateBatchById(pmBillList);
//        pmBillDetailDao.updateBatchById(pmBillDetailList);

        int i = 1/0;
    }


    private List<PmBillExcelData> loadFromExcel(File file){
        EasyExcelFactory.read(file,PmBillExcelData.class,new PmBillDataListener(file.getName(),pmBillDataDao)).build().readAll();
        return Collections.emptyList();
    }

    @Override
    @Transactional
    public void recoverData() {
        List<PmBillExcelData> list = pmBillDataDao.list(new LambdaQueryWrapper<PmBillExcelData>().isNull(PmBillExcelData::getBillId));
/*        List<PmBill> pmBillList = new ArrayList<>();
        List<PmBillDetail> detailList = new ArrayList<>();*/
        Date date = new Date();
        int billId = 6798;
        int id = 6243;
        for (PmBillExcelData data : list) {
            PmBill pmBill = PmBill.builder()
                    .billid(billId++)
                    .orgid(data.getOrgid())
                    .orderid(data.getOrderId())
                    .sourcetype(Integer.parseInt(data.getBalanceNode()))
                    .sourcecode(data.getSourcecode())
                    .billcost(new BigDecimal(data.getPrice()))
                    .sourceid(data.getOrderId())
                    .status(0)
                    .createtime(date)
                    .createuserid(21582)
                    .build();
            PmBill negativePmBill = PmBill.builder()
                    .billid(billId++)
                    .orgid(data.getOrgid())
                    .orderid(data.getOrderId())
                    .sourcetype(Integer.parseInt(data.getBalanceNode()))
                    .sourcecode(data.getSourcecode())
                    .billcost(new BigDecimal(data.getPrice()).multiply(new BigDecimal("-1")))
                    .sourceid(data.getOrderId())
                    .status(0)
                    .remark("电站终止生成反向账单")
                    .createtime(date)
                    .createuserid(21582)
                    .build();
            pmBillDao.save(pmBill);
            pmBillDao.save(negativePmBill);
            BigDecimal balanceRate = BigDecimal.ZERO ;
            if(data.getSourcecode().equals("10")) {
                balanceRate = new BigDecimal("50");
            }
            if(data.getSourcecode().equals("20")) {
                balanceRate = new BigDecimal("30");
            }
            if(data.getSourcecode().equals("30")) {
                balanceRate = new BigDecimal("20");
            }
            PmBillDetail pmBillDetail = PmBillDetail.builder()
                    .id(id++)
                    .billid(pmBill.getBillid())
                    .orderid(pmBill.getOrderid())
                    .totalpower(Integer.parseInt(data.getTotalPower()))
                    .price(new BigDecimal(data.getPriceUnit()))
                    .balancerate(balanceRate)
                    .createtime(date)
                    .build();
            PmBillDetail negativePmBillDetail = PmBillDetail.builder()
                    .id(id++)
                    .billid(negativePmBill.getBillid())
                    .orderid(pmBill.getOrderid())
                    .totalpower(Integer.parseInt(data.getTotalPower()) * -1)
                    .price(new BigDecimal(data.getPriceUnit()))
                    .balancerate(balanceRate)
                    .createtime(date)
                    .build();
            pmBillDetailDao.save(pmBillDetail);
            pmBillDetailDao.save(negativePmBillDetail);
        }



    }
}
